package cn.com.acca.ma.service.impl;

import cn.com.acca.ma.common.util.DateUtil;
import cn.com.acca.ma.common.util.HttpClientUtil;
import cn.com.acca.ma.common.util.ModelConverter;
import cn.com.acca.ma.common.util.PropertiesUtil;
import cn.com.acca.ma.constant.FilterMethod;
import cn.com.acca.ma.constant.ShippingSpaceControlInRealTransaction;
import cn.com.acca.ma.constant.StockInfoMark;
import cn.com.acca.ma.model.*;
import cn.com.acca.ma.pojo.*;
import cn.com.acca.ma.service.RealStockTransactionRecordService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class RealStockTransactionRecordServiceImpl extends BaseServiceImpl<RealStockTransactionRecordServiceImpl, RealStockTransactionRecord> implements
        RealStockTransactionRecordService {

    /**
     * 实时地判断买卖条件，给出交易建议，并保存在文件中
     */
    @Override
    public void realTimeJudgeConditionAndGiveSuggestion() {
        logger.info("开始实时地判断买卖条件，给出交易建议，并保存在文件中");

        // 买卖建议字符串
        StringBuffer printRealBuySellSuggestion = new StringBuffer();

        // 参数
        String date = PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.realtime.judge.condition.give.suggestion.date");
        boolean historyDataJudge = Boolean.parseBoolean(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.history.data.judge.condition.give.suggestion"));
        Integer backwardMonth = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.stock.success.rate.backward.month"));
        Integer averageDateNumber = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.success.rate.average.date.number"));
        Double macdMultiplicationFactor = Double.parseDouble(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.success.rate.average.date.macd.multiplication.factor"));
        Double closePriceMa5MultiplicationFactor = Double.parseDouble(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.success.rate.average.date.closePriceMa5.multiplication.factor"));
        Double heiKinAshiMultiplicationFactor = Double.parseDouble(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.success.rate.average.date.heiKinAshi.multiplication.factor"));
        Double kdMultiplicationFactor = Double.parseDouble(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.success.rate.average.date.kd.multiplication.factor"));
        Integer transactionStrategy = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.strategy"));
        Double threshold = Double.parseDouble(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.strategy.success.rate.threshold"));
        String xrBeginDate = PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.xr.begin.date");
        String highestLowestPriceBeginDate = PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.current.closePrice.compareTo.someTime.highest.lowest.price.begin.date");
        Integer currentClosePriceCompareToSomeTimeHighestPrice = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.current.closePrice.compareTo.someTime.highest.price"));
        Integer currentClosePriceCompareToSomeTimeLowestPrice = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.current.closePrice.compareTo.someTime.lowest.price"));
        Integer closePriceStart = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.closePrice.start"));
        Integer closePriceEnd = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.closePrice.end"));
        Integer oneStockTransactionCapitalAmount = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.one.stock.transaction.capital.amount"));
        Boolean useMinFilterConditionWhenBuy = Boolean.parseBoolean(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.useMinFilterConditionWhenBuy"));
        Boolean useMinFilterConditionWhenSell = Boolean.parseBoolean(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.useMinFilterConditionWhenSell"));
        Integer shippingSpaceControl = Integer.parseInt(PropertiesUtil.getValue(MODEL_FILTER_PROPERTIES, "filter.real.transaction.shippingSpaceControl"));

        /*********************************** 应该有的仓位，使用哪种算法 *********************************/
        // 计算所有算法的近期的成功率/百分比
        List<SuccessRateOrPercentagePojo> macdGoldCrossList = null;
        List<SuccessRateOrPercentagePojo> macdDeadCrossList = null;
        List<SuccessRateOrPercentagePojo> closePriceMa5GoldCrossList = null;
        List<SuccessRateOrPercentagePojo> closePriceMa5DeadCrossList = null;
        List<SuccessRateOrPercentagePojo> heiKinAshiUpDownList = null;
        List<SuccessRateOrPercentagePojo> heiKinAshiDownUpList = null;
        List<SuccessRateOrPercentagePojo> kdGoldCrossList = null;
        List<SuccessRateOrPercentagePojo> kdDeadCrossList = null;
        String beginDate = DateUtil.dateToString(DateUtil.stepMonth(DateUtil.stringToDate(date), -backwardMonth));
        String transactionStrategyString = null;
        if (transactionStrategy.equals(TransactionStrategy.GOLD_CROSS_DEAD_CROSS_SUCCESS_RATE)) {
            transactionStrategyString = "使用金叉死叉算法的【成功率】作为标准";
            logger.info(transactionStrategyString);

            macdGoldCrossList = modelMACDGoldCrossDao.getMACDGoldCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * macdMultiplicationFactor.doubleValue()));
            macdDeadCrossList = modelMACDDeadCrossDao.getMACDDeadCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * macdMultiplicationFactor.doubleValue()));
            closePriceMa5GoldCrossList = modelClosePriceMA5GoldCrossDao.getClosePriceMa5GoldCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * closePriceMa5MultiplicationFactor.doubleValue()));
            closePriceMa5DeadCrossList = modelClosePriceMA5DeadCrossDao.getClosePriceMa5DeadCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * closePriceMa5MultiplicationFactor.doubleValue()));
            heiKinAshiUpDownList = modelHeiKinAshiUpDownDao.getHeiKinAshiUpDownSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * heiKinAshiMultiplicationFactor.doubleValue()));
            heiKinAshiDownUpList = modelHeiKinAshiDownUpDao.getHeiKinAshiDownUpSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * heiKinAshiMultiplicationFactor.doubleValue()));
            kdGoldCrossList = modelKDGoldCrossDao.getKdGoldCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * kdMultiplicationFactor.doubleValue()));
            kdDeadCrossList = modelKDDeadCrossDao.getKdDeadCrossSuccessRate(false, beginDate, date, (int) (averageDateNumber.intValue() * kdMultiplicationFactor.doubleValue()));
        }
        if (transactionStrategy.equals(TransactionStrategy.GOLD_CROSS_DEAD_CROSS_PERCENTAGE)) {
            transactionStrategyString = "使用金叉死叉算法的【百分比】作为标准";
            logger.info(transactionStrategyString);

            macdGoldCrossList = modelMACDGoldCrossDao.getMACDGoldCrossPercentage(false, beginDate, date);
            macdDeadCrossList = modelMACDDeadCrossDao.getMACDDeadCrossPercentage(false, beginDate, date);
            closePriceMa5GoldCrossList = modelClosePriceMA5GoldCrossDao.getClosePriceMa5GoldCrossPercentage(false, beginDate, date);
            closePriceMa5DeadCrossList = modelClosePriceMA5DeadCrossDao.getClosePriceMa5DeadCrossPercentage(false, beginDate, date);
            heiKinAshiUpDownList = modelHeiKinAshiUpDownDao.getHeiKinAshiUpDownPercentage(false, beginDate, date);
            heiKinAshiDownUpList = modelHeiKinAshiDownUpDao.getHeiKinAshiDownUpPercentage(false, beginDate, date);
            kdGoldCrossList = modelKDGoldCrossDao.getKdGoldCrossPercentage(false, beginDate, date);
            kdDeadCrossList = modelKDDeadCrossDao.getKdDeadCrossPercentage(false, beginDate, date);
        }

        // 判断哪种算法的成功率/百分比最高
        FilterMethod.SELECT_FILTER_METHOD_VALUE = 0.0;
        FilterMethod.SELECT_FILTER_METHOD = null;
        Double macdGoldCrossSuccessRateValue = null;
        if (null != macdGoldCrossList && macdGoldCrossList.size() > 0) {
            macdGoldCrossSuccessRateValue = Double.valueOf(macdGoldCrossList.get(macdGoldCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("MACD金叉算法的成功率/百分比【" + macdGoldCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(macdGoldCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = macdGoldCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.MACD_GOLD_CROSS;
            }
        }
        Double macdDeadCrossSuccessRateValue = null;
        if (null != macdDeadCrossList && macdDeadCrossList.size() > 0) {
            macdDeadCrossSuccessRateValue = Double.valueOf(macdDeadCrossList.get(macdDeadCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("MACD死叉算法的成功率/百分比【" + macdDeadCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(macdDeadCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = macdDeadCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.MACD_DEAD_CROSS;
            }
        }
        Double closePriceMa5GoldCrossSuccessRateValue = null;
        if (null != closePriceMa5GoldCrossList && closePriceMa5GoldCrossList.size() > 0) {
            closePriceMa5GoldCrossSuccessRateValue = Double.valueOf(closePriceMa5GoldCrossList.get(closePriceMa5GoldCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("close_price金叉ma5算法的成功率/百分比【" + closePriceMa5GoldCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(closePriceMa5GoldCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = closePriceMa5GoldCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.CLOSE_PRICE_GOLD_CROSS_MA;
            }
        }
        Double closePriceMa5DeadCrossSuccessRateValue = null;
        if (null != closePriceMa5DeadCrossList && closePriceMa5DeadCrossList.size() > 0) {
            closePriceMa5DeadCrossSuccessRateValue = Double.valueOf(closePriceMa5DeadCrossList.get(closePriceMa5DeadCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("close_price死叉ma5算法的成功率/百分比【" + closePriceMa5DeadCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(closePriceMa5DeadCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = closePriceMa5DeadCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.CLOSE_PRICE_DEAD_CROSS_MA;
            }
        }
        Double heiKinAshiUpDownSuccessRateValue = null;
        if (null != heiKinAshiUpDownList && heiKinAshiUpDownList.size() > 0) {
            heiKinAshiUpDownSuccessRateValue = Double.valueOf(heiKinAshiUpDownList.get(heiKinAshiUpDownList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("hei kin ashi上升趋势算法的成功率/百分比【" + heiKinAshiUpDownSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(heiKinAshiUpDownSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = heiKinAshiUpDownSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.HEI_KIN_ASHI_UP_DOWN;
            }
        }
        Double heiKinAshiDownUpSuccessRateValue = null;
        if (null != heiKinAshiDownUpList && heiKinAshiDownUpList.size() > 0) {
            heiKinAshiDownUpSuccessRateValue = Double.valueOf(heiKinAshiDownUpList.get(heiKinAshiDownUpList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("hei kin ashi下跌趋势算法的成功率/百分比【" + heiKinAshiDownUpSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(heiKinAshiDownUpSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = heiKinAshiDownUpSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.HEI_KIN_ASHI_DOWN_UP;
            }
        }
        Double kdGoldCrossSuccessRateValue = null;
        if (null != kdGoldCrossList && kdGoldCrossList.size() > 0) {
            kdGoldCrossSuccessRateValue = Double.valueOf(kdGoldCrossList.get(kdGoldCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("KD金叉算法的成功率/百分比【" + kdGoldCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(kdGoldCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = kdGoldCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.KD_GOLD_CROSS;
            }
        }
        Double kdDeadCrossSuccessRateValue = null;
        if (null != kdDeadCrossList && kdDeadCrossList.size() > 0) {
            kdDeadCrossSuccessRateValue = Double.valueOf(kdDeadCrossList.get(kdDeadCrossList.size() - 1).getSuccessRateOrPercentage().toString());
            logger.info("KD死叉算法的成功率/百分比【" + kdDeadCrossSuccessRateValue + "】");
            if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(kdDeadCrossSuccessRateValue)) {
                FilterMethod.SELECT_FILTER_METHOD_VALUE = kdDeadCrossSuccessRateValue;
                FilterMethod.SELECT_FILTER_METHOD = FilterMethod.KD_DEAD_CROSS;
            }
        }

        // 如果最大的过滤算法成功率/百分比比阈值低，则不做任何交易
        String lessThanThresholdMessage;
        if (-1 == FilterMethod.SELECT_FILTER_METHOD_VALUE.compareTo(threshold)) {
            lessThanThresholdMessage = "所有的过滤算法中最大的成功率是/百分比【" + FilterMethod.SELECT_FILTER_METHOD_VALUE
                    + "】，对应的过滤算法是【" + FilterMethod.SELECT_FILTER_METHOD + "】，小于阈值【"
                    + threshold + "】，因此不做任何交易";
            logger.info(lessThanThresholdMessage);
            FilterMethod.SELECT_FILTER_METHOD = null;
        } else {
            lessThanThresholdMessage = "采用的过滤算法【" + FilterMethod.SELECT_FILTER_METHOD + "】，其成功率/百分比【"
                    + FilterMethod.SELECT_FILTER_METHOD_VALUE + "】";
            logger.info(lessThanThresholdMessage);
        }

        // 确定仓位
        Integer shippingSpace = null;
        if (shippingSpaceControl.equals(ShippingSpaceControlInRealTransaction.YES)) {
            shippingSpace = Double.valueOf(Math.ceil(FilterMethod.SELECT_FILTER_METHOD_VALUE / 10) > 10 ? 10.0 : Math.ceil(FilterMethod.SELECT_FILTER_METHOD_VALUE / 10)).intValue();
        }
        if (shippingSpaceControl.equals(ShippingSpaceControlInRealTransaction.NO)) {
            shippingSpace = 10;
        }

        BullStockSuggestionList bullStockSuggestionList = new BullStockSuggestionList();
        ShortStockSuggestionList shortStockSuggestionList = new ShortStockSuggestionList();
        /*********************************** 卖股票/还券的建议 *********************************/
        // 查找real_stock_transaction_record表中，sell_date、sell_price、sell_amount列都为空的记录
        List<StockInfoPojo> shouldSellBullStockList = new ArrayList<>();
        List<RealStockTransactionRecord> holdBullStockNumberList = realStockTransactionRecordDao.findBySellDateNullAndSellPriceNullAndSellAmountNull();
        for (int i = 0; i < holdBullStockNumberList.size(); i++) {
            RealStockTransactionRecord realStockTransactionRecord = holdBullStockNumberList.get(i);
            StockInfo stockInfo = stockInfoDao.getStockInfoObjectByStockCode(realStockTransactionRecord.getStockCode());

            // 开盘价，最新价，最高价，最低价
            BigDecimal newestOpenPrice = null;
            BigDecimal newestClosePrice = null;
            BigDecimal newestHighestPrice = null;
            BigDecimal newestLowestPrice = null;
            if (!historyDataJudge) {
                // 像股票代码为510300（ETF300）这种股票在stock_info表中没有，此处只能continue
                if (null == stockInfo) {
                    logger.warn("股票【" + realStockTransactionRecord.getStockCode() + "】在表stock_info中没有记录");
                    continue;
                }
                String content = null;
                try {
                    content = HttpClientUtil.get(HQ_SINAJS_URL_PREFIX + stockInfo.getUrlParam());
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (URISyntaxException e) {
                    e.printStackTrace();
                }
                JSONObject jsonObject = JSONObject.parseObject(content);
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                JSONObject param = jsonArray.getJSONObject(0);
                newestOpenPrice = new BigDecimal(param.getDouble("open"));
                newestClosePrice = new BigDecimal(param.getDouble("current"));
                newestHighestPrice = new BigDecimal(param.getDouble("high"));
                newestLowestPrice = new BigDecimal(param.getDouble("low"));
            } else {
                if (realStockTransactionRecord.getStockCode().equals("600757")) {
                    int x = 0;
                }

                StockTransactionDataAll tempStockTransactionDataAll = stockTransactionDataDao.findByCodeAndDate(stockInfo.getUrlParam().substring(2), DateUtil.stringToDate(date));
                if (null == tempStockTransactionDataAll) {
                    logger.warn("股票【" + stockInfo.getCode() + "】，日期【" + date + "】在表stock_transaction_data_all中没有记录");
                    continue;
                }
                newestOpenPrice = tempStockTransactionDataAll.getOpenPrice();
                newestClosePrice = tempStockTransactionDataAll.getClosePrice();
                newestHighestPrice = tempStockTransactionDataAll.getHighestPrice();
                newestLowestPrice = tempStockTransactionDataAll.getLowestPrice();
            }

            RealTransactionCondition realTransactionCondition = realTransactionConditionDao.findByStockCode(realStockTransactionRecord.getStockCode());

            // 判断是否macd死叉
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getMacdDeadCrossClosePrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.MACD_GOLD_CROSS
                    && newestClosePrice.compareTo(realTransactionCondition.getMacdDeadCrossClosePrice()) <= 0) {
                StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                shouldSellBullStockList.add(stockInfoPojo);
            }
            // 判断是否close_price死叉ma5
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getCPMa5DCClosePrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.CLOSE_PRICE_GOLD_CROSS_MA
                    && newestClosePrice.compareTo(realTransactionCondition.getCPMa5DCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) <= 0) {
                StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                shouldSellBullStockList.add(stockInfoPojo);
            }
            // 判断是否hei_kin_ashi下跌趋势
            if (null != realTransactionCondition
//                    && null != realTransactionCondition.getHKADownHKAOpenPrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.HEI_KIN_ASHI_UP_DOWN) {
                BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
                Date previousDate = stockTransactionDataDao.findPreviousDateByDate(false, date);
                StockTransactionData preStockTransactionData = stockTransactionDataDao.findLastByCodeAndDate(realTransactionCondition.getStockCode(), previousDate);
                BigDecimal heiKinAshiOpenPrice = null;
                if (null == preStockTransactionData) {
                    heiKinAshiOpenPrice = newestOpenPrice.add(newestClosePrice).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                } else {
                    heiKinAshiOpenPrice = heiKinAshiOpenPrice = preStockTransactionData.getHaOpenPrice().add(preStockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                }
                if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) < 0) {
                    StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                    shouldSellBullStockList.add(stockInfoPojo);
                }
            }
            // 判断是否kd死叉
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getKdDeadCrossRsv()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.KD_GOLD_CROSS) {
                Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                Object[] d = (Object[]) object;
                BigDecimal highestPrice = (BigDecimal) d[0];
                BigDecimal lowestPrice = (BigDecimal) d[1];
                if (highestPrice.compareTo(newestHighestPrice) == -1){
                    highestPrice = newestHighestPrice;
                }
                if (lowestPrice.compareTo(newestLowestPrice) == 1){
                    lowestPrice = newestLowestPrice;
                }
                BigDecimal closePrice = realTransactionCondition.getKdDeadCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                if (newestClosePrice.compareTo(closePrice) <= 0) {
                    StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                    shouldSellBullStockList.add(stockInfoPojo);
                }
            }
        }
        bullStockSuggestionList.setShouldSellBullStockList(shouldSellBullStockList);
        // 查找real_stock_transaction_record表中，buy_date、buy_price、buy_amount列都为空的记录
        List<StockInfoPojo> shouldBuyShortStockList = new ArrayList<>();
        List<RealStockTransactionRecord> holdShortStockNumberList = realStockTransactionRecordDao.findByBuyDateNullAndBuyPriceNullAndBuyAmountNull();
        for (int i = 0; i < holdShortStockNumberList.size(); i++) {
            RealStockTransactionRecord realStockTransactionRecord = holdShortStockNumberList.get(i);
            StockInfo stockInfo = stockInfoDao.getStockInfoObjectByStockCode(realStockTransactionRecord.getStockCode());

            // 开盘价，最新价，最高价，最低价
            BigDecimal newestOpenPrice = null;
            BigDecimal newestClosePrice = null;
            BigDecimal newestHighestPrice = null;
            BigDecimal newestLowestPrice = null;
            if (!historyDataJudge) {
                // 像股票代码为510300（ETF300）这种股票在stock_info表中没有，此处只能continue
                if (null == stockInfo) {
                    logger.warn("股票【" + realStockTransactionRecord.getStockCode() + "】在表stock_info中没有记录");
                    continue;
                }
                String content = null;
                try {
                    content = HttpClientUtil.get(HQ_SINAJS_URL_PREFIX + stockInfo.getUrlParam());
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (URISyntaxException e) {
                    e.printStackTrace();
                }
                JSONObject jsonObject = JSONObject.parseObject(content);
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                JSONObject param = jsonArray.getJSONObject(0);
                newestOpenPrice = new BigDecimal(param.getDouble("open"));
                newestClosePrice = new BigDecimal(param.getDouble("current"));
                newestHighestPrice = new BigDecimal(param.getDouble("high"));
                newestLowestPrice = new BigDecimal(param.getDouble("low"));
            } else {
                if (realStockTransactionRecord.getStockCode().equals("600757")) {
                    int x = 0;
                }

                StockTransactionDataAll tempStockTransactionDataAll = stockTransactionDataDao.findByCodeAndDate(stockInfo.getUrlParam().substring(2), DateUtil.stringToDate(date));
                if (null == tempStockTransactionDataAll) {
                    logger.warn("股票【" + stockInfo.getCode() + "】，日期【" + date + "】在表stock_transaction_data_all中没有记录");
                    continue;
                }
                newestOpenPrice = tempStockTransactionDataAll.getOpenPrice();
                newestClosePrice = tempStockTransactionDataAll.getClosePrice();
                newestHighestPrice = tempStockTransactionDataAll.getHighestPrice();
                newestLowestPrice = tempStockTransactionDataAll.getLowestPrice();
            }

            RealTransactionCondition realTransactionCondition = realTransactionConditionDao.findByStockCode(realStockTransactionRecord.getStockCode());

            // 判断是否macd金叉
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getMacdGoldCrossClosePrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.MACD_DEAD_CROSS
                    && newestClosePrice.compareTo(realTransactionCondition.getMacdGoldCrossClosePrice()) >= 0) {
                StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                shouldBuyShortStockList.add(stockInfoPojo);
            }
            // 判断是否close_price金叉ma5
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getCPMa5GCClosePrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.CLOSE_PRICE_DEAD_CROSS_MA
                    && newestClosePrice.compareTo(realTransactionCondition.getCPMa5GCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) >= 0) {
                StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                shouldBuyShortStockList.add(stockInfoPojo);
            }
            // 判断是否hei_kin_ashi上涨趋势
            if (null != realTransactionCondition
//                    && null != realTransactionCondition.getHKAUpHKAOpenPrice()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.HEI_KIN_ASHI_DOWN_UP) {
                BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
                Date previousDate = stockTransactionDataDao.findPreviousDateByDate(false, date);
                StockTransactionData preStockTransactionData = stockTransactionDataDao.findLastByCodeAndDate(realTransactionCondition.getStockCode(), previousDate);
                BigDecimal heiKinAshiOpenPrice = null;
                if (null == preStockTransactionData) {
                    heiKinAshiOpenPrice = newestOpenPrice.add(newestClosePrice).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                } else {
                    heiKinAshiOpenPrice = preStockTransactionData.getHaOpenPrice().add(preStockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                }
                if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) > 0) {
                    StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                    shouldBuyShortStockList.add(stockInfoPojo);
                }
            }
            // 判断是否kd金叉
            if (null != realTransactionCondition
                    && null != realTransactionCondition.getKdGoldCrossRsv()
                    && realStockTransactionRecord.getFilterType() == FilterMethod.KD_DEAD_CROSS) {
                Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                Object[] d = (Object[]) object;
                BigDecimal highestPrice = (BigDecimal) d[0];
                BigDecimal lowestPrice = (BigDecimal) d[1];
                if (highestPrice.compareTo(newestHighestPrice) == -1){
                    highestPrice = newestHighestPrice;
                }
                if (lowestPrice.compareTo(newestLowestPrice) == 1){
                    lowestPrice = newestLowestPrice;
                }
                BigDecimal closePrice = realTransactionCondition.getKdGoldCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                if (newestClosePrice.compareTo(closePrice) >= 0) {
                    StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                    shouldBuyShortStockList.add(stockInfoPojo);
                }
            }
        }
        shortStockSuggestionList.setShouldBuyShortStockList(shouldBuyShortStockList);

        /*********************************** 买股票/融券的建议 *********************************/
        List<StockInfoPojo> shouldBuyBullStockList = new ArrayList<>();
        List<StockInfoPojo> shouldSellShortStockList = new ArrayList<>();
        List<StockInfoPojo> macdGoldCrossShouldBuyStockList = new ArrayList<>();
        List<StockInfoPojo> macdDeadCrossShouldSellStockList = new ArrayList<>();
        List<StockInfoPojo> closePriceGoldCrossMa5ShouldBuyStockList = new ArrayList<>();
        List<StockInfoPojo> closePriceDeadCrossMa5ShouldSellStockList = new ArrayList<>();
        List<StockInfoPojo> heiKinAshiUpDownShouldBuyStockList = new ArrayList<>();
        List<StockInfoPojo> heiKinAshiDownUpShouldSellStockList = new ArrayList<>();
        List<StockInfoPojo> kdGoldCrossShouldBuyStockList = new ArrayList<>();
        List<StockInfoPojo> kdDeadCrossShouldSellStockList = new ArrayList<>();
        if (null != FilterMethod.SELECT_FILTER_METHOD) {
            // 判断做多/做空时，是使用所有过滤条件，还是使用最少的过滤条件
            boolean allFilterCondition = true;
            if (useMinFilterConditionWhenSell) {
                allFilterCondition = false;
            }
            if (useMinFilterConditionWhenBuy) {
                allFilterCondition = false;
            }
            List<RealTransactionCondition> realTransactionConditionList = realTransactionConditionDao.findByCondition(allFilterCondition);
            if (null != realTransactionConditionList && realTransactionConditionList.size() > 0) {
                for (int i = 0; i < realTransactionConditionList.size(); i++) {
                    RealTransactionCondition realTransactionCondition = realTransactionConditionList.get(i);
                    StockInfo stockInfo = stockInfoDao.getStockInfoObjectByStockCode(realTransactionCondition.getStockCode());

                    // 开盘价，最新价，最高价，最低价
                    BigDecimal newestOpenPrice = null;
                    BigDecimal newestClosePrice = null;
                    BigDecimal newestHighestPrice = null;
                    BigDecimal newestLowestPrice = null;
                    if (!historyDataJudge) {
                        // 像股票代码为510300（ETF300）这种股票在stock_info表中没有，此处只能continue
                        if (null == stockInfo) {
                            logger.warn("股票【" + stockInfo.getCode() + "】在表stock_info中没有记录");
                            continue;
                        }
                        String content = null;
                        try {
                            content = HttpClientUtil.get(HQ_SINAJS_URL_PREFIX + stockInfo.getUrlParam());
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        } catch (URISyntaxException e) {
                            e.printStackTrace();
                        }
                        JSONObject jsonObject = JSONObject.parseObject(content);
                        JSONArray jsonArray = jsonObject.getJSONArray("data");
                        JSONObject param = jsonArray.getJSONObject(0);
                        newestOpenPrice = new BigDecimal(param.getDouble("open"));
                        newestClosePrice = new BigDecimal(param.getDouble("current"));
                        newestHighestPrice = new BigDecimal(param.getDouble("high"));
                        newestLowestPrice = new BigDecimal(param.getDouble("low"));
                    } else {
                        if (stockInfo.getCode().equals("600757")) {
                            int x = 0;
                        }

                        StockTransactionDataAll tempStockTransactionDataAll = stockTransactionDataDao.findByCodeAndDate(stockInfo.getUrlParam().substring(2), DateUtil.stringToDate(date));
                        if (null == tempStockTransactionDataAll) {
                            logger.warn("股票【" + stockInfo.getCode() + "】，日期【" + date + "】在表stock_transaction_data_all中没有记录");
                            continue;
                        }
                        newestOpenPrice = tempStockTransactionDataAll.getOpenPrice();
                        newestClosePrice = tempStockTransactionDataAll.getClosePrice();
                        newestHighestPrice = tempStockTransactionDataAll.getHighestPrice();
                        newestLowestPrice = tempStockTransactionDataAll.getLowestPrice();
                    }

                    if (FilterMethod.SELECT_FILTER_METHOD % 2 == 1) {
                        // 如果当前价格/某段时间的最高收盘价>参数currentClosePriceCompareToSomeTimeHighestPrice，则跳过
                        BigDecimal maxHighestPrice = stockTransactionDataDao.findMaxHighestPriceBetweenDate(realTransactionCondition.getStockCode(), highestLowestPriceBeginDate, date);
//                        BigDecimal b1 = newestClosePrice.divide(maxClosePrice, 2, BigDecimal.ROUND_HALF_UP);
//                        double d1 = b1.doubleValue();
                        if (newestClosePrice.divide(maxHighestPrice, 4, BigDecimal.ROUND_HALF_UP).doubleValue() * 100 > currentClosePriceCompareToSomeTimeHighestPrice.doubleValue()) {
                            continue;
                        }
                    } else {
                        // 如果当前价格/某段时间的最低收盘价<参数currentClosePriceCompareToSomeTimeLowestPrice，则跳过
                        BigDecimal minLowestPrice = stockTransactionDataDao.findMinLowestPriceBetweenDate(realTransactionCondition.getStockCode(), highestLowestPriceBeginDate, date);
                        if (newestClosePrice.divide(minLowestPrice, 4, BigDecimal.ROUND_HALF_UP).doubleValue() * 100 < currentClosePriceCompareToSomeTimeLowestPrice.doubleValue()) {
                            continue;
                        }
                    }

                    // 如果当前价格不在区间之内，则跳过
                    if (newestClosePrice.doubleValue() < closePriceStart || newestClosePrice.doubleValue() > closePriceEnd) {
                        continue;
                    }

                    // 如果这只股票当日除权了，则跳过
                    BigDecimal previousClosePrice = stockTransactionDataDao.findLastClosePriceByCodeAndDate(false, realTransactionCondition.getStockCode(), date);
                    double downPercentage = newestClosePrice.subtract(previousClosePrice).divide(previousClosePrice, 2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
                    Date judgementDate = DateUtil.stringToDate("2020-08-24");
                    if (DateUtil.stringToDate(xrBeginDate).before(judgementDate)
                            && downPercentage < -11) {
                        continue;
                    }
                    if ((DateUtil.stringToDate(xrBeginDate).after(judgementDate) || DateUtil.stringToDate(xrBeginDate).equals(judgementDate))
                            && stockInfo.getCode().startsWith("300")
                            && downPercentage < -22) {
                        continue;
                    }
                    if ((DateUtil.stringToDate(xrBeginDate).after(judgementDate) || DateUtil.stringToDate(xrBeginDate).equals(judgementDate))
                            && !stockInfo.getCode().startsWith("300")
                            && downPercentage < -11) {
                        continue;
                    }

                    if (FilterMethod.SELECT_FILTER_METHOD % 2 == 1) {
                        // 如果这只股票不是ma120单调不递减，则跳过（除了计算之前那些天-1的，还要计算当前日期的）
//                        if (!stockTransactionDataDao.ma120NotDecreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)){
                        if (!realTransactionCondition.getIsMa120NotDecreasing().equals(1)
                                || !stockTransactionDataDao.isMa120NotDecreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)) {
                            continue;
                        }
                        // 如果这只股票不是ma250单调不递减，则跳过（除了计算之前那些天-1的，还要计算当前日期的）
//                        if (!stockTransactionDataDao.ma250NotDecreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)){
                        if (!realTransactionCondition.getIsMa250NotDecreasing().equals(1)
                                || !stockTransactionDataDao.isMa250NotDecreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)) {
                            continue;
                        }
                    } else {
                        // 如果这只股票不是ma120单调不递增，则跳过（除了计算之前那些天-1的，还要计算当前日期的）
//                        if (!stockTransactionDataDao.ma120NotIncreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)){
                        if (!realTransactionCondition.getIsMa120NotIncreasing().equals(1)
                                || !stockTransactionDataDao.isMa120NotIncreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)) {
                            continue;
                        }
                        // 如果这只股票不是ma250单调不递增，则跳过（除了计算之前那些天-1的，还要计算当前日期的）
//                        if (!stockTransactionDataDao.ma250NotIncreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)){
                        if (!realTransactionCondition.getIsMa250NotIncreasing().equals(1)
                                || !stockTransactionDataDao.isMa250NotIncreasing(realTransactionCondition.getStockCode(), newestClosePrice, date)) {
                            continue;
                        }
                    }

                    // 要计算的是前一天的数据
                    String lastDate = DateUtil.dateToString(stockTransactionDataDao.findPreviousDateByDate(false, date));
                    StockTransactionData stockTransactionData = stockTransactionDataDao.findLastByCodeAndDate(stockInfo.getCode(), DateUtil.stringToDate(lastDate));
                    // macd金叉
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getMacdGoldCrossClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.MACD_GOLD_CROSS
                            && newestClosePrice.compareTo(realTransactionCondition.getMacdGoldCrossClosePrice()) >= 0) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        shouldBuyBullStockList.add(stockInfoPojo);
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getMacdGoldCrossClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.MACD_GOLD_CROSS
                            && newestClosePrice.compareTo(realTransactionCondition.getMacdGoldCrossClosePrice()) >= 0) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        macdGoldCrossShouldBuyStockList.add(stockInfoPojo);
                    }
                    // macd死叉
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getMacdDeadCrossClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.MACD_DEAD_CROSS
                            && newestClosePrice.compareTo(realTransactionCondition.getMacdDeadCrossClosePrice()) <= 0
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        shouldSellShortStockList.add(stockInfoPojo);
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getMacdDeadCrossClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.MACD_DEAD_CROSS
                            && newestClosePrice.compareTo(realTransactionCondition.getMacdDeadCrossClosePrice()) <= 0
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        macdDeadCrossShouldSellStockList.add(stockInfoPojo);
                    }
                    // close_price金叉ma5
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getCPMa5GCClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.CLOSE_PRICE_GOLD_CROSS_MA
                            && newestClosePrice.compareTo(realTransactionCondition.getCPMa5GCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) >= 0) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        shouldBuyBullStockList.add(stockInfoPojo);
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getCPMa5GCClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.CLOSE_PRICE_GOLD_CROSS_MA
                            && newestClosePrice.compareTo(realTransactionCondition.getCPMa5GCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) >= 0) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        closePriceGoldCrossMa5ShouldBuyStockList.add(stockInfoPojo);
                    }
                    // close_price死叉ma5
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getCPMa5DCClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.CLOSE_PRICE_DEAD_CROSS_MA
                            && newestClosePrice.compareTo(realTransactionCondition.getCPMa5DCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) <= 0
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        shouldSellShortStockList.add(stockInfoPojo);
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getCPMa5DCClosePrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.CLOSE_PRICE_DEAD_CROSS_MA
                            && newestClosePrice.compareTo(realTransactionCondition.getCPMa5DCClosePrice().multiply(new BigDecimal(4)).add(newestClosePrice).divide(new BigDecimal(5), 2, BigDecimal.ROUND_HALF_UP)) <= 0
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                        stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                        closePriceDeadCrossMa5ShouldSellStockList.add(stockInfoPojo);
                    }
                    // hei_kin_ashi上涨趋势
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getHKAUpHKAOpenPrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.HEI_KIN_ASHI_UP_DOWN) {
                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                        if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) > 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            shouldBuyBullStockList.add(stockInfoPojo);
                        }
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getHKAUpHKAOpenPrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.HEI_KIN_ASHI_UP_DOWN) {
                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
                        if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) > 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            heiKinAshiUpDownShouldBuyStockList.add(stockInfoPojo);
                        }
                    }
                    // hei_kin_ashi下跌趋势
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getHKADownHKAOpenPrice()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.HEI_KIN_ASHI_DOWN_UP
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
//                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4));
                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
//                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getClosePrice()).divide(new BigDecimal(2));
                        if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) < 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            shouldSellShortStockList.add(stockInfoPojo);
                        }
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getHKADownHKAOpenPrice()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.HEI_KIN_ASHI_DOWN_UP
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4), 2, BigDecimal.ROUND_HALF_UP);
//                        BigDecimal heiKinAshiClosePrice = newestOpenPrice.add(newestClosePrice).add(newestHighestPrice).add(newestLowestPrice).divide(new BigDecimal(4));
                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getHaClosePrice()).divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
//                        BigDecimal heiKinAshiOpenPrice = stockTransactionData.getHaOpenPrice().add(stockTransactionData.getClosePrice()).divide(new BigDecimal(2));
                        if (heiKinAshiClosePrice.compareTo(heiKinAshiOpenPrice) < 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            heiKinAshiDownUpShouldSellStockList.add(stockInfoPojo);
                        }
                    }
                    // kd金叉
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getKdGoldCrossRsv()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.KD_GOLD_CROSS) {
                        Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                        Object[] d = (Object[]) object;
                        BigDecimal highestPrice = (BigDecimal) d[0];
                        BigDecimal lowestPrice = (BigDecimal) d[1];
                        if (highestPrice.compareTo(newestHighestPrice) == -1){
                            highestPrice = newestHighestPrice;
                        }
                        if (lowestPrice.compareTo(newestLowestPrice) == 1){
                            lowestPrice = newestLowestPrice;
                        }
                        BigDecimal closePrice = realTransactionCondition.getKdGoldCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                        if (newestClosePrice.compareTo(closePrice) >= 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            shouldBuyBullStockList.add(stockInfoPojo);
                        }
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getKdGoldCrossRsv()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.KD_GOLD_CROSS) {
                        Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                        Object[] d = (Object[]) object;
                        BigDecimal highestPrice = (BigDecimal) d[0];
                        BigDecimal lowestPrice = (BigDecimal) d[1];
                        if (highestPrice.compareTo(newestHighestPrice) == -1){
                            highestPrice = newestHighestPrice;
                        }
                        if (lowestPrice.compareTo(newestLowestPrice) == 1){
                            lowestPrice = newestLowestPrice;
                        }
                        BigDecimal closePrice = realTransactionCondition.getKdGoldCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                        if (newestClosePrice.compareTo(closePrice) >= 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            kdGoldCrossShouldBuyStockList.add(stockInfoPojo);
                        }
                    }
                    // kd死叉
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getKdDeadCrossRsv()
                            && FilterMethod.SELECT_FILTER_METHOD == FilterMethod.KD_DEAD_CROSS
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                        Object[] d = (Object[]) object;
                        BigDecimal highestPrice = (BigDecimal) d[0];
                        BigDecimal lowestPrice = (BigDecimal) d[1];
                        if (highestPrice.compareTo(newestHighestPrice) == -1){
                            highestPrice = newestHighestPrice;
                        }
                        if (lowestPrice.compareTo(newestLowestPrice) == 1){
                            lowestPrice = newestLowestPrice;
                        }
                        BigDecimal closePrice = realTransactionCondition.getKdDeadCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                        if (newestClosePrice.compareTo(closePrice) <= 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            shouldSellShortStockList.add(stockInfoPojo);
                        }
                    }
                    if (null != realTransactionCondition
                            && null != realTransactionCondition.getKdDeadCrossRsv()
                            && FilterMethod.SELECT_FILTER_METHOD != FilterMethod.KD_DEAD_CROSS
                            && null != stockInfo.getMark()
                            && stockInfo.getMark().equals(StockInfoMark.SECURITIES_LENDING)) {
                        Object object = stockTransactionDataDao.findHighestAndLowestClosePriceByCodeAndDateInEightDay(stockInfo.getCode(), DateUtil.stringToDate(date));
                        Object[] d = (Object[]) object;
                        BigDecimal highestPrice = (BigDecimal) d[0];
                        BigDecimal lowestPrice = (BigDecimal) d[1];
                        if (highestPrice.compareTo(newestHighestPrice) == -1){
                            highestPrice = newestHighestPrice;
                        }
                        if (lowestPrice.compareTo(newestLowestPrice) == 1){
                            lowestPrice = newestLowestPrice;
                        }
                        BigDecimal closePrice = realTransactionCondition.getKdDeadCrossRsv().divide(new BigDecimal(100)).multiply(highestPrice.subtract(lowestPrice)).add(lowestPrice);
                        if (newestClosePrice.compareTo(closePrice) <= 0) {
                            StockInfoPojo stockInfoPojo = ModelConverter.stockInfoToStockInfoPojo(stockInfo);
                            stockInfoPojo.setAmount(((int) (oneStockTransactionCapitalAmount.intValue() / newestClosePrice.doubleValue()) / 100 * 100));
                            kdDeadCrossShouldSellStockList.add(stockInfoPojo);
                        }
                    }
                }
                bullStockSuggestionList.setShouldBuyBullStockList(shouldBuyBullStockList);
                shortStockSuggestionList.setShouldSellShortStockList(shouldSellShortStockList);
            } else {
                logger.warn("没有买入股票/融券的建议");
            }
        }

        /*********************************** 打印卖出建议和买入建议 *********************************/
        super.printlnAndCollectString(printRealBuySellSuggestion, "-------------------------------------------------------------------------");
        // 打印使用哪种交易策略
        super.printlnAndCollectString(printRealBuySellSuggestion, transactionStrategyString);
        // 打印最大成功率是否小于阈值
        super.printlnAndCollectString(printRealBuySellSuggestion, lessThanThresholdMessage);
        // 打印各种算法的成功率/百分比
        super.printlnAndCollectString(printRealBuySellSuggestion, "MACD金叉算法的成功率/百分比【" + macdGoldCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "MACD死叉算法的成功率/百分比【" + macdDeadCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "close_price金叉ma5算法的成功率/百分比【" + closePriceMa5GoldCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "close_price死叉ma5算法的成功率/百分比【" + closePriceMa5DeadCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "hei_kin_ashi上涨趋势算法的成功率/百分比【" + heiKinAshiUpDownSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "hei_kin_ashi下跌趋势算法的成功率/百分比【" + heiKinAshiDownUpSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "KD金叉算法的成功率/百分比【" + kdGoldCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, "KD死叉算法的成功率/百分比【" + kdDeadCrossSuccessRateValue + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, null);
        // 打印应该有的仓位
        super.printlnAndCollectString(printRealBuySellSuggestion, "应该有的仓位【" + shippingSpace + "】，应该使用的算法为【" + FilterMethod.SELECT_FILTER_METHOD + "】");
        super.printlnAndCollectString(printRealBuySellSuggestion, null);
        // 打印融券/买入股票的建议
        super.printlnAndCollectString(printRealBuySellSuggestion, "应该卖出/还券的股票：");
        if (null != bullStockSuggestionList && null != bullStockSuggestionList.getShouldSellBullStockList()
                && bullStockSuggestionList.getShouldSellBullStockList().size() > 0) {
            for (StockInfoPojo stockInfoPojo : bullStockSuggestionList.getShouldSellBullStockList()) {
                super.printlnAndCollectString(printRealBuySellSuggestion, "之前买入，现在应该卖出的股票：" + stockInfoPojo.getName() + "      " + stockInfoPojo.getCode());
            }
        } else {
            super.printlnAndCollectString(printRealBuySellSuggestion, "没有之前买入，现在应该卖出的股票的建议");
        }
        if (null != shortStockSuggestionList && null != shortStockSuggestionList.getShouldBuyShortStockList()
                && shortStockSuggestionList.getShouldBuyShortStockList().size() > 0) {
            for (StockInfoPojo stockInfoPojo : shortStockSuggestionList.getShouldBuyShortStockList()) {
                super.printlnAndCollectString(printRealBuySellSuggestion, "之前融券，现在应该还券的股票：" + stockInfoPojo.getName() + "      " + stockInfoPojo.getCode());
            }
        } else {
            super.printlnAndCollectString(printRealBuySellSuggestion, "没有之前融券，现在应该还券的股票的建议");
        }
        super.printlnAndCollectString(printRealBuySellSuggestion, null);
        // 计算能买的股票/融券的数量
        Integer canBuyOrSellStockNumber = shippingSpace - (holdBullStockNumberList != null ? holdBullStockNumberList.size() : 0) - (holdShortStockNumberList != null ? holdShortStockNumberList.size() : 0);
        // 打印买入股票/融券的建议
        if (0 == canBuyOrSellStockNumber) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "总共可以买入/融券的股票数量为【" + ((holdBullStockNumberList != null ? holdBullStockNumberList.size() : 0) + (holdShortStockNumberList != null ? holdShortStockNumberList.size() : 0)) + "】");
            super.printlnAndCollectString(printRealBuySellSuggestion, "仓位已满，不需要再买入股票/融券。现在的仓位是【" + shippingSpace + "】");
            super.printlnAndCollectString(printRealBuySellSuggestion, null);
            if (null != bullStockSuggestionList && null != bullStockSuggestionList.getShouldBuyBullStockList()
                    && bullStockSuggestionList.getShouldBuyBullStockList().size() > 0) {
                for (int j = 0; j < bullStockSuggestionList.getShouldBuyBullStockList().size(); j++) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "原本可以考虑买入的股票：" + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getName() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getCode() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getAmount());
                }
            }
            if (null != shortStockSuggestionList && null != shortStockSuggestionList.getShouldSellShortStockList()
                    && shortStockSuggestionList.getShouldSellShortStockList().size() > 0) {
                for (int j = 0; j < shortStockSuggestionList.getShouldSellShortStockList().size(); j++) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "原本可以考虑融券的股票：" + shortStockSuggestionList.getShouldSellShortStockList().get(j).getName() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(j).getCode() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(j).getAmount());
                }
            }
        } else {
            if (null != FilterMethod.SELECT_FILTER_METHOD && FilterMethod.SELECT_FILTER_METHOD % 2 == 1 && null != bullStockSuggestionList
                    && null != bullStockSuggestionList.getShouldBuyBullStockList()
                    && bullStockSuggestionList.getShouldBuyBullStockList().size() > 0) {
                super.printlnAndCollectString(printRealBuySellSuggestion, "现在是多头占优势，以买入股票为主");
                super.printlnAndCollectString(printRealBuySellSuggestion, null);
                int otherStockNumber = 0;
                for (int i = 0; i < bullStockSuggestionList.getShouldBuyBullStockList().size() && canBuyOrSellStockNumber > 0; i++, canBuyOrSellStockNumber--) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "应该买入的股票/融券：" + bullStockSuggestionList.getShouldBuyBullStockList().get(i).getName() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(i).getCode() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(i).getAmount());
                    otherStockNumber = i + 1;
                }
                super.printlnAndCollectString(printRealBuySellSuggestion, null);
                for (int j = otherStockNumber; j < bullStockSuggestionList.getShouldBuyBullStockList().size(); j++) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "其余可以考虑买入的股票/融券：" + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getName() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getCode() + "  " + bullStockSuggestionList.getShouldBuyBullStockList().get(j).getAmount());
                }
            } else if (null != FilterMethod.SELECT_FILTER_METHOD && FilterMethod.SELECT_FILTER_METHOD % 2 == 0 && null != shortStockSuggestionList
                    && null != shortStockSuggestionList.getShouldSellShortStockList()
                    && shortStockSuggestionList.getShouldSellShortStockList().size() > 0) {
                super.printlnAndCollectString(printRealBuySellSuggestion, "现在是空头占优势，以融券为主");
                super.printlnAndCollectString(printRealBuySellSuggestion, null);
                int otherStockNumber = 0;
                for (int i = 0; i < shortStockSuggestionList.getShouldSellShortStockList().size() && canBuyOrSellStockNumber > 0; i++, canBuyOrSellStockNumber--) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "应该融券/买入的股票：" + shortStockSuggestionList.getShouldSellShortStockList().get(i).getName() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(i).getCode() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(i).getAmount());
                    otherStockNumber = i + 1;
                }
                super.printlnAndCollectString(printRealBuySellSuggestion, null);
                for (int j = otherStockNumber; j < shortStockSuggestionList.getShouldSellShortStockList().size(); j++) {
                    super.printlnAndCollectString(printRealBuySellSuggestion, "其余可以考虑融券/买入的股票：" + shortStockSuggestionList.getShouldSellShortStockList().get(j).getName() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(j).getCode() + "  " + shortStockSuggestionList.getShouldSellShortStockList().get(j).getAmount());
                }
            } else {
                super.printlnAndCollectString(printRealBuySellSuggestion, "没有买入股票/融券的建议");
            }
        }
        super.printlnAndCollectString(printRealBuySellSuggestion, null);
        // 成功率不是最高的算法，可以考虑买入的股票
        super.printlnAndCollectString(printRealBuySellSuggestion, "成功率不是最高的算法，可以考虑买入的股票/融券：");
        if (null != macdGoldCrossShouldBuyStockList && macdGoldCrossShouldBuyStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "MACD金叉算法，可以考虑买入的股票：");
            for (int i = 0; i < macdGoldCrossShouldBuyStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, macdGoldCrossShouldBuyStockList.get(i).getCode() + "    " + macdGoldCrossShouldBuyStockList.get(i).getName() + "    " + macdGoldCrossShouldBuyStockList.get(i).getAmount());
            }
        }
        if (null != macdDeadCrossShouldSellStockList && macdDeadCrossShouldSellStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "MACD死叉算法，可以考虑融券：");
            for (int i = 0; i < macdDeadCrossShouldSellStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, macdDeadCrossShouldSellStockList.get(i).getCode() + "    " + macdDeadCrossShouldSellStockList.get(i).getName() + "    " + macdDeadCrossShouldSellStockList.get(i).getAmount());
            }
        }
        if (null != closePriceGoldCrossMa5ShouldBuyStockList && closePriceGoldCrossMa5ShouldBuyStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "close_price金叉ma5算法，可以考虑买入的股票：");
            for (int i = 0; i < closePriceGoldCrossMa5ShouldBuyStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, closePriceGoldCrossMa5ShouldBuyStockList.get(i).getCode() + "    " + closePriceGoldCrossMa5ShouldBuyStockList.get(i).getName() + "    " + closePriceGoldCrossMa5ShouldBuyStockList.get(i).getAmount());
            }
        }
        if (null != closePriceDeadCrossMa5ShouldSellStockList && closePriceDeadCrossMa5ShouldSellStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "close_price死叉ma5算法，可以考虑融券：");
            for (int i = 0; i < closePriceDeadCrossMa5ShouldSellStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, closePriceDeadCrossMa5ShouldSellStockList.get(i).getCode() + "    " + closePriceDeadCrossMa5ShouldSellStockList.get(i).getName() + "    " + closePriceDeadCrossMa5ShouldSellStockList.get(i).getAmount());
            }
        }
        if (null != heiKinAshiUpDownShouldBuyStockList && heiKinAshiUpDownShouldBuyStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "hei_kin_ashi上涨趋势算法，可以考虑买入的股票：");
            for (int i = 0; i < heiKinAshiUpDownShouldBuyStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, heiKinAshiUpDownShouldBuyStockList.get(i).getCode() + "    " + heiKinAshiUpDownShouldBuyStockList.get(i).getName() + "    " + heiKinAshiUpDownShouldBuyStockList.get(i).getAmount());
            }
        }
        if (null != heiKinAshiDownUpShouldSellStockList && heiKinAshiDownUpShouldSellStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "hei_kin_ashi下跌趋势算法，可以考虑融券：");
            for (int i = 0; i < heiKinAshiDownUpShouldSellStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, heiKinAshiDownUpShouldSellStockList.get(i).getCode() + "    " + heiKinAshiDownUpShouldSellStockList.get(i).getName() + "    " + heiKinAshiDownUpShouldSellStockList.get(i).getAmount());
            }
        }
        if (null != kdGoldCrossShouldBuyStockList && kdGoldCrossShouldBuyStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "kd金叉算法，可以考虑买入的股票：");
            for (int i = 0; i < kdGoldCrossShouldBuyStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, kdGoldCrossShouldBuyStockList.get(i).getCode() + "    " + kdGoldCrossShouldBuyStockList.get(i).getName() + "    " + kdGoldCrossShouldBuyStockList.get(i).getAmount());
            }
        }
        if (null != kdDeadCrossShouldSellStockList && kdDeadCrossShouldSellStockList.size() > 0) {
            super.printlnAndCollectString(printRealBuySellSuggestion, "kd死叉算法，可以考虑融券：");
            for (int i = 0; i < kdDeadCrossShouldSellStockList.size(); i++) {
                super.printlnAndCollectString(printRealBuySellSuggestion, kdDeadCrossShouldSellStockList.get(i).getCode() + "    " + kdDeadCrossShouldSellStockList.get(i).getName() + "    " + kdDeadCrossShouldSellStockList.get(i).getAmount());
            }
        }
        super.printlnAndCollectString(printRealBuySellSuggestion, "-------------------------------------------------------------------------");

        /*********************************** 将买卖建议保存到文件中 *********************************/
        // 保存真实交易的买卖建议
        File file;
        try {
            file = new File(PRINT_REAL_BUY_SELL_SUGGESTION);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter writer = new FileWriter(file);
            writer.write(printRealBuySellSuggestion.toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        logger.info("实时地判断买卖条件，给出交易建议，并保存在文件中完成");
    }

    @Override
    public String listToString(List list) {
        return null;
    }


}
